package com.cf.code.core;


import com.cf.util.ReflectionUtil;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import org.springframework.core.OrderComparator;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * cf-game-BaseGenerator
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/3/1 16:51
 */
public class CodePageGenerator {

    public void generateTemplate(Class clazz, String outPath) throws Exception {
        List<CodePage> codePages = this.templateParameter(clazz, outPath);
        for (CodePage codePage : codePages) {
            Configuration configuration = new Configuration();
            configuration.setObjectWrapper(new DefaultObjectWrapper());
            configuration.setTemplateLoader(new ClassTemplateLoader(CodePageGenerator.class, codePage.getTemplatePath()));
            Template template = configuration.getTemplate(codePage.getTemplateName());
            StringWriter writer = new StringWriter();
            template.process(codePage, writer);
            OutputStream outputStream = createOutPutPath(codePage.getOutPutPath(), codePage.getOutPutName());
            if (outputStream == null) {
                System.out.println("文件已存在，不允许重复创建，请先拷贝该文件，在生成！");
                continue;
            }
            outputStream.write(writer.toString().getBytes("utf-8"));
        }
    }

    private OutputStream createOutPutPath(String outPutPath, String outPutName) throws Exception {
        Assert.notNull(outPutName, "输出的文件名字不能为空！");
        if (!StringUtils.isEmpty(outPutPath)) {
            File file = new File(outPutPath);
            if (!file.exists()) {
                file.mkdirs();
            }
        } else {
            outPutPath = "./";
        }

        File targetFile = new File(outPutPath + outPutName);
        if (targetFile.exists()) {
            return null;
        }
        return new FileOutputStream(targetFile);
    }


    protected List<CodePage> templateParameter(Class clazz, String outPath) {
        CModel cModel = (CModel) clazz.getAnnotation(CModel.class);
        CPage[] pages = cModel.pages();
        List<CodePage> codePages = new ArrayList<>();
        for (CPage page : pages) {
            codePages.add(createCodePages(clazz, page, outPath));
        }
        return codePages;
    }

    private CodePage createCodePages(Class clazz, CPage page, String outPath) {
        CodePage codePage = new CodePage();
        String templateName = page.templateName();
        Assert.notNull(templateName, "模板的文件名字不能为空！");
        codePage.setOutPutName(page.outPutName());
        codePage.setOutPutPath(outPath);
        codePage.setTemplateName(templateName);
        codePage.setTemplatePath(page.templatePath());
        codePage.setTitle(page.title());
        codePage.setPath(page.path());
        List<Field> fields = ReflectionUtil.getFields(clazz);

        if (fields == null || fields.size() <= 0)
            return codePage;

        List<CodeField> codeFields = new ArrayList();
        fields.forEach(field -> {
            CField cField = field.getAnnotation(CField.class);
            if (cField != null) {
                CodeField codeField = new CodeField();
                codeField.setDefaultValue(cField.defaultValue());
                codeField.setLab(cField.lab());
                codeField.setOrder(cField.order());
                codeField.setSearch(cField.search());
                codeField.setType(cField.type());
                codeField.setDisable(cField.disable());
                codeField.setName(field.getName());
                codeField.setShow(cField.show());
                codeField.setDataUrl(cField.dataUrl());
                codeField.setSelectKey(cField.selectKey());
                codeField.setSelectValue(cField.selectValue());
                codeField.setUploadPath(cField.uploadPath());
                codeFields.add(codeField);
            }
        });
        OrderComparator.sort(codeFields);
        codePage.setFieldList(codeFields);

        return codePage;
    }
}
